package mornd.test1;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.Resource;

import java.lang.reflect.Field;
import java.util.Map;

/**
 * @author: mornd
 * @dateTime: 2023/5/4 - 13:30
 *
 * DefaultListableBeanFactory - BeanFactory 的默认实现
 *  而单例池 singletonObjects 是在其父类 DefaultSingletonBeanRegistry 中
 * AnnotationConfigServletWebServerApplicationContext ioc 的默认实现，也就是 run 方法的实际返回类型
 *
 */
@SpringBootApplication
public class App {
    public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext context = SpringApplication.run(App.class, args);

        // 通过反射获取单例池对象
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        Field field = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
        field.setAccessible(true);
        Map<String, Object> singletonObjects = (Map<String, Object>) field.get(beanFactory);
        singletonObjects.forEach((k,v) -> {
            //System.out.println(k + ":" + v);
        });

        // getBean的具体实现是通过 getBeanFactory() 也就是 DefaultListableBeanFactory 实现
        Component1 bean = (Component1) context.getBean("component1");
        bean.register();

        /**
         * ApplicationContext 接口继承的六大接口：
         *
         * ListableBeanFactory
         * HierarchicalBeanFactory
         *
         * MessageSource  国际化
         * ResourcePatternResolver (通配符)访问资源能力
         * ApplicationEventPublisher 发布事件
         * EnvironmentCapable 获取系统环境以及 *.yml 类路径下的配置文件值
         */

        //System.out.println(context.getMessage("key", new Object[]{"张三", "男"}, Locale.CANADA));
        //System.out.println(context.getMessage("key", new Object[]{"tom", "male"}, Locale.ENGLISH));

        // classpath*:xxx 搜索区域扩大至jar包中
        Resource[] resources = context.getResources("classpath:application.properties");

        // 获取环境信息
        ConfigurableEnvironment environment = context.getEnvironment();
        System.out.println(environment.getSystemEnvironment().get("Java_Home"));
        System.out.println(environment.getProperty("name")); // 自定义的配置文件中

        // 发布事件
        context.publishEvent(new UserRegisterEvent(context));
    }
}
